package top.hjcwzx.wrench.limiter.utils;

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class SpELUtil {

    private static final ExpressionParser parser = new SpelExpressionParser();

    private String parseKey(String keySpel, Method method, Object[] args, Object target) {
        if (keySpel == null || keySpel.trim().isEmpty()) {
            // 没写key就默认用类名+方法名
            return method.getDeclaringClass().getName() + "." + method.getName();
        }
        try {
            Expression expression = parser.parseExpression(keySpel);
            EvaluationContext context = new StandardEvaluationContext(target);

            if (args != null && args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    context.setVariable("p" + i, args[i]);
                }
            }
            // 解析SpEL表达式，返回限流Key
            String key = expression.getValue(context, String.class);
            if (key == null || key.trim().isEmpty()) {
                // 如果表达式没解析出key，降级用方法全名
                return method.getDeclaringClass().getName() + "." + method.getName();
            }
            return key;
        } catch (Exception e) {
            e.printStackTrace();
            // 出错也用方法全名，保证限流不受影响
            return method.getDeclaringClass().getName() + "." + method.getName();
        }
    }

    public static String parse(String expression, Method method, Object[] args) {
        EvaluationContext context = new StandardEvaluationContext();

        // 获取参数名列表
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            context.setVariable(parameters[i].getName(), args[i]);
        }

        Expression exp = parser.parseExpression(expression);
        return method.getDeclaringClass().getName() + "." + method.getName() + "#" + exp.getValue(context, String.class);
    }
}
